#include "stdafx.h"

#include "ResourceLoader.h"


using namespace std;

namespace ZeEngine
{
    ResourceLoader::ResourceLoader(SDL_Renderer* pRenderer) : m_pRenderer(pRenderer)
    {

    }
    /*
    int ResourceLoader::LoadImage(const string iFileName, Sint32* width, Sint32* height, Sint32* bpp, bool createMipmap) 
    {	   
        GLint texture = -1;
	    SDL_Surface *surface = NULL;
	    if ( (surface = IMG_Load(iFileName.c_str())) != NULL ) 
        {
		    //This function will also free the sdl surface
		    texture = CreateTexture(surface, iFileName, width, height, bpp, createMipmap);

		    if (texture == -1) 
            {
			    LOG_ERROR("Error loading: " + iFileName);
			    return -1;
		    }
        }
	    else 
        {
            LOG_ERROR(IMG_GetError());
		    return -1;
	    }

        LOG_INFORMATION("Loaded " + iFileName);
        return texture;
    }

    */

    
    SDL_Texture* ResourceLoader::LoadTexture(const std::string& iFileName)
    {            
        //The final texture
        SDL_Texture* newTexture = NULL;

        //Load image at specified path
        SDL_Surface* loadedSurface = IMG_Load( iFileName.c_str() );

        if( loadedSurface == NULL )
        {
            LOG_ERROR( "Unable to load image " + iFileName + " SDL_image Error: " +  string(IMG_GetError()) );
        }
        else
        {
            //Create texture from surface pixels
            newTexture = SDL_CreateTextureFromSurface( m_pRenderer, loadedSurface );
            if( newTexture == NULL )
            {
                LOG_ERROR( "Unable to load image " + iFileName + " SDL Error: " +  string(IMG_GetError()) );
            }

            //Get rid of old loaded surface
            SDL_FreeSurface( loadedSurface );
        }

        return newTexture;
    }
    
    /*
    Sint32 ResourceLoader::getPixel(SDL_Surface *surface, int x, int y)
    {

	    if(x <= surface->w && y <= surface->h) {
		    int bpp = surface->format->BytesPerPixel;
		     //Here p is the address to the pixel we want to retrieve 
		    Uint8 *p = (Uint8 *)surface->pixels + (y * surface->pitch) + (x * bpp);

		    switch(bpp) {
			    case 1:
				    return *p;
			    case 2:
				    return *(Uint16 *)p;
			    case 3:
				    if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
					    return p[0] << 16 | p[1] << 8 | p[2];
				    else
					    return p[0] | p[1] << 8 | p[2] << 16;
			    case 4:
				    return *(Uint32 *)p;
			    default:
				    return 0;        //shouldn't happen, but avoids warnings 
		    }
	    }

	    return -1;
    }
    */
    
    void ResourceLoader::UnloadTexture(SDL_Texture* pTexture)
    {
        SDL_DestroyTexture(pTexture);
    }

    /*
    void ResourceLoader::UnloadImage(GLuint handle, const string& iFileName)
    {
        LOG_INFORMATION("Unloaded Texture " + iFileName);
        glDeleteTextures(1, &handle);
    }
    */
    int ResourceLoader::CreateTexture(SDL_Surface* surface, const string& iFileName, Sint32* width, Sint32* height, Sint32* bpp, bool createMipmap) 
    {
        /*
	    GLuint texture;
	    GLenum texture_format;
	    GLint nOfColors;

	    if ( surface ) 
        {
		    // Check that the image's width is a power of 2
		    if ( (surface->w & (surface->w - 1)) != 0 ) 
            {
			    //LOG_WARNING(iFileName + " width is not a power of 2");
		    }

		    // Also check if the height is a power of 2
		    if ( (surface->h & (surface->h - 1)) != 0 ) 
            {
			    //LOG_WARNING(iFileName + " height is not a power of 2");
		    }

		    // get the number of channels in the SDL surface
		    nOfColors = surface->format->BytesPerPixel;

		    if (nOfColors == 4)     // contains an alpha channel
		    {
			    if (surface->format->Rmask == 0x000000ff)
				    texture_format = GL_RGBA;
			    else
				    texture_format = GL_BGRA;
		    }
		    else if (nOfColors == 3)     // no alpha channel
		    {
			    if (surface->format->Rmask == 0x000000ff)
				    texture_format = GL_RGB;
			    else
				    texture_format = GL_BGR;
		    }
		    else 
            {
			    LOG_WARNING("The image " + iFileName + " is not truecolor...  this will probably break");
			    return (-1);
		    }

		    // Have OpenGL generate a texture object handle for us
		    glGenTextures( 1, &texture );

		    // Bind the texture object
		    glBindTexture( GL_TEXTURE_2D, texture );

		    *width = surface->w;
		    *height = surface->h;
		    *bpp = surface->format->BytesPerPixel;

		    // Set the texture's stretching properties
		    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		    //May need to tone down the quality of these textures for the lab
		    if (createMipmap) {
			    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, surface->w, surface->h,
				    texture_format, GL_UNSIGNED_BYTE, surface->pixels);

			    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
			    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		    }
		    else {
			    glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
				    texture_format, GL_UNSIGNED_BYTE, surface->pixels );

			    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
			    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
		    }
	    }
	    else 
        {
		    LOG_ERROR(SDL_GetError());
		    return(-1);
	    }

	    // Free the SDL_Surface only if it was successfully created
	    if ( surface ) 
        {
		    SDL_FreeSurface( surface );
	    }

	    return texture;
        */

        return 0;
    }

    /*
    Mix_Chunk* ResourceLoader::loadSound(const std::string iFileName)
    {
        Mix_Chunk *wSound = NULL;
        wSound = Mix_LoadWAV(iFileName.c_str());

        if(wSound == NULL) {
	        LOG_ERROR(Mix_GetError());
            return NULL;
        }
        
        LOG_INFORMATION("Loaded " + iFileName);
        return wSound;
    }
    
    void ResourceLoader::unloadSound(Mix_Chunk* iSound, const std::string iFileName)
    {
        Mix_FreeChunk(iSound);
        LOG_INFORMATION("Unloaded " + iFileName);
    }

    bool ResourceLoader::loadFont(const std::string iFileName)
    {
        /*
	    //Create font
	    GLuint wTextureName;
	    glGenTextures(1, &wTextureName);

	    try 
        {
		    oFont.Create(iFileName, wTextureName);
	    }
	    catch(GLFontError::InvalidFile) 
        {
            LOG_ERROR("Error loading font " + iFileName);
            return false;
	    }
*/
    /*
        return true;
    }
    */
}
